<template>
  <div class="audio-detection">
    <!-- 页面标题 -->
    <div class="page-header">
      <h1>AI音频检测</h1>
      <p>识别AI语音合成和语音克隆内容</p>
    </div>

    <!-- 音频上传区域 -->
    <div class="upload-section">
      <div class="upload-area" @dragover.prevent @drop="handleDrop">
        <div class="upload-icon">🎤</div>
        <h3>上传音频文件</h3>
        <p>支持 WAV, MP3, M4A 格式，最大 50MB</p>
        <input 
          ref="fileInput" 
          type="file" 
          accept="audio/*" 
          @change="handleFileUpload"
          style="display: none;"
        />
        <button class="upload-btn" @click="$refs.fileInput.click()">
          选择音频文件
        </button>
      </div>
      
      <div class="record-section">
        <h3>实时录音</h3>
        <div class="record-controls">
          <button 
            class="record-btn"
            :class="{ recording: isRecording }"
            @click="toggleRecording"
          >
            {{ isRecording ? '🛑 停止录音' : '🎙️ 开始录音' }}
          </button>
          <div v-if="isRecording" class="recording-time">
            录音时长: {{ formatTime(recordingTime) }}
          </div>
        </div>
      </div>
    </div>

    <!-- 音频播放和分析 -->
    <div v-if="currentAudio" class="audio-section">
      <div class="audio-player">
        <div class="player-header">
          <h3>{{ currentAudio.name }}</h3>
          <div class="audio-info">
            <span>大小: {{ formatFileSize(currentAudio.size) }}</span>
            <span>时长: {{ formatTime(audioDuration) }}</span>
          </div>
        </div>
        
        <div class="player-controls">
          <audio 
            ref="audioPlayer" 
            :src="currentAudio.url" 
            @loadeddata="onAudioLoaded"
            @timeupdate="onTimeUpdate"
            @ended="onAudioEnded"
          ></audio>
          
          <div class="control-buttons">
            <button @click="togglePlayPause" class="play-btn">
              {{ isPlaying ? '⏸️' : '▶️' }}
            </button>
            <div class="time-display">
              {{ formatTime(currentTime) }} / {{ formatTime(audioDuration) }}
            </div>
            <div class="volume-control">
              <input 
                type="range" 
                min="0" 
                max="1" 
                step="0.1" 
                v-model="volume"
                @input="changeVolume"
              />
            </div>
          </div>
          
          <div class="waveform-container">
            <canvas ref="waveformCanvas" width="600" height="100"></canvas>
          </div>
        </div>
        
        <div class="analysis-controls">
          <button 
            class="analyze-btn"
            @click="startAnalysis"
            :disabled="isAnalyzing"
          >
            {{ isAnalyzing ? '分析中...' : '开始分析' }}
          </button>
          <button class="quick-check-btn" @click="quickCheck">
            快速检测
          </button>
        </div>
      </div>
    </div>

    <!-- 检测结果 -->
    <div v-if="analysisResult" class="result-section">
      <div class="result-header">
        <h2>检测结果</h2>
        <div class="overall-score">
          <div class="score-circle" :class="getScoreClass(analysisResult.aiProbability)">
            {{ analysisResult.aiProbability }}%
          </div>
          <div class="score-label">AI生成概率</div>
        </div>
      </div>
      
      <div class="result-tabs">
        <button 
          v-for="tab in resultTabs" 
          :key="tab.id"
          class="tab-btn"
          :class="{ active: activeTab === tab.id }"
          @click="activeTab = tab.id"
        >
          {{ tab.label }}
        </button>
      </div>
      
      <div class="result-content">
        <!-- 基本分析 -->
        <div v-if="activeTab === 'basic'" class="basic-analysis">
          <div class="analysis-grid">
            <div class="analysis-card">
              <h3>语音特征</h3>
              <div class="feature-list">
                <div class="feature-item">
                  <span class="label">语音类型：</span>
                  <span class="value">{{ analysisResult.voiceType }}</span>
                </div>
                <div class="feature-item">
                  <span class="label">语言：</span>
                  <span class="value">{{ analysisResult.language }}</span>
                </div>
                <div class="feature-item">
                  <span class="label">说话人性别：</span>
                  <span class="value">{{ analysisResult.gender }}</span>
                </div>
                <div class="feature-item">
                  <span class="label">情绪状态：</span>
                  <span class="value">{{ analysisResult.emotion }}</span>
                </div>
              </div>
            </div>
            
            <div class="analysis-card">
              <h3>技术指标</h3>
              <div class="metrics-list">
                <div class="metric-item">
                  <span class="metric-label">自然度：</span>
                  <div class="metric-bar">
                    <div class="metric-fill" :style="{ width: analysisResult.naturalness + '%' }"></div>
                  </div>
                  <span class="metric-value">{{ analysisResult.naturalness }}%</span>
                </div>
                <div class="metric-item">
                  <span class="metric-label">流畅度：</span>
                  <div class="metric-bar">
                    <div class="metric-fill" :style="{ width: analysisResult.fluency + '%' }"></div>
                  </div>
                  <span class="metric-value">{{ analysisResult.fluency }}%</span>
                </div>
                <div class="metric-item">
                  <span class="metric-label">音质：</span>
                  <div class="metric-bar">
                    <div class="metric-fill" :style="{ width: analysisResult.quality + '%' }"></div>
                  </div>
                  <span class="metric-value">{{ analysisResult.quality }}%</span>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 声纹分析 -->
        <div v-if="activeTab === 'voiceprint'" class="voiceprint-analysis">
          <div class="voiceprint-display">
            <h3>声纹特征</h3>
            <canvas ref="voiceprintCanvas" width="400" height="200"></canvas>
          </div>
          
          <div class="voiceprint-details">
            <h3>声纹特征分析</h3>
            <div class="details-grid">
              <div class="detail-item">
                <span class="detail-label">基频变化：</span>
                <span class="detail-value">{{ analysisResult.pitchVariation }}</span>
              </div>
              <div class="detail-item">
                <span class="detail-label">共振峰分布：</span>
                <span class="detail-value">{{ analysisResult.formantDistribution }}</span>
              </div>
              <div class="detail-item">
                <span class="detail-label">频谱特征：</span>
                <span class="detail-value">{{ analysisResult.spectralFeatures }}</span>
              </div>
              <div class="detail-item">
                <span class="detail-label">韵律特征：</span>
                <span class="detail-value">{{ analysisResult.prosodyFeatures }}</span>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 异常检测 -->
        <div v-if="activeTab === 'anomaly'" class="anomaly-analysis">
          <h3>异常检测</h3>
          <div class="anomaly-list">
            <div 
              v-for="anomaly in analysisResult.anomalies" 
              :key="anomaly.id"
              class="anomaly-item"
              :class="anomaly.severity"
            >
              <div class="anomaly-icon">{{ anomaly.icon }}</div>
              <div class="anomaly-content">
                <h4>{{ anomaly.title }}</h4>
                <p>{{ anomaly.description }}</p>
                <div class="anomaly-location">
                  <span>时间位置: {{ formatTime(anomaly.timestamp) }}</span>
                  <button class="play-segment-btn" @click="playSegment(anomaly.timestamp)">
                    播放片段
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 检测历史 -->
    <div class="history-section">
      <h2>检测历史</h2>
      <div class="history-grid">
        <div 
          v-for="record in detectionHistory" 
          :key="record.id"
          class="history-card"
        >
          <div class="history-header">
            <h4>{{ record.name }}</h4>
            <div class="history-result" :class="getScoreClass(record.score)">
              {{ record.score }}%
            </div>
          </div>
          <div class="history-details">
            <p>{{ record.date }}</p>
            <p>{{ record.type }}</p>
          </div>
          <div class="history-actions">
            <button class="replay-btn" @click="replayAudio(record)">
              重新播放
            </button>
            <button class="reanalyze-btn" @click="reanalyzeAudio(record)">
              重新分析
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

// 响应式数据
const currentAudio = ref(null)
const audioPlayer = ref(null)
const waveformCanvas = ref(null)
const voiceprintCanvas = ref(null)
const isPlaying = ref(false)
const isRecording = ref(false)
const isAnalyzing = ref(false)
const currentTime = ref(0)
const audioDuration = ref(0)
const volume = ref(1)
const recordingTime = ref(0)
const analysisResult = ref(null)
const activeTab = ref('basic')

// 结果标签页
const resultTabs = [
  { id: 'basic', label: '基本分析' },
  { id: 'voiceprint', label: '声纹分析' },
  { id: 'anomaly', label: '异常检测' }
]

// 检测历史
const detectionHistory = ref([
  {
    id: 1,
    name: '语音消息.wav',
    date: '2024-01-15 14:30',
    type: '语音合成',
    score: 85
  },
  {
    id: 2,
    name: '电话录音.mp3',
    date: '2024-01-15 14:25',
    type: '真实语音',
    score: 23
  }
])

// 录音相关
let mediaRecorder = null
let recordingInterval = null
let audioChunks = []

// 方法
const handleDrop = (e) => {
  e.preventDefault()
  const files = Array.from(e.dataTransfer.files)
  if (files.length > 0) {
    processFile(files[0])
  }
}

const handleFileUpload = (e) => {
  const file = e.target.files[0]
  if (file) {
    processFile(file)
  }
}

const processFile = (file) => {
  if (file.type.startsWith('audio/')) {
    const url = URL.createObjectURL(file)
    currentAudio.value = {
      name: file.name,
      size: file.size,
      url: url
    }
    
    // 重置状态
    analysisResult.value = null
    isAnalyzing.value = false
    isPlaying.value = false
    currentTime.value = 0
  }
}

const toggleRecording = async () => {
  if (isRecording.value) {
    stopRecording()
  } else {
    startRecording()
  }
}

const startRecording = async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
    mediaRecorder = new MediaRecorder(stream)
    audioChunks = []
    
    mediaRecorder.ondataavailable = (event) => {
      audioChunks.push(event.data)
    }
    
    mediaRecorder.onstop = () => {
      const audioBlob = new Blob(audioChunks, { type: 'audio/wav' })
      const url = URL.createObjectURL(audioBlob)
      currentAudio.value = {
        name: `录音_${new Date().toLocaleTimeString()}.wav`,
        size: audioBlob.size,
        url: url
      }
    }
    
    mediaRecorder.start()
    isRecording.value = true
    recordingTime.value = 0
    
    recordingInterval = setInterval(() => {
      recordingTime.value += 1
    }, 1000)
  } catch (error) {
    console.error('录音失败:', error)
  }
}

const stopRecording = () => {
  if (mediaRecorder) {
    mediaRecorder.stop()
    mediaRecorder.stream.getTracks().forEach(track => track.stop())
  }
  
  isRecording.value = false
  clearInterval(recordingInterval)
}

const onAudioLoaded = () => {
  audioDuration.value = audioPlayer.value.duration
  drawWaveform()
}

const onTimeUpdate = () => {
  currentTime.value = audioPlayer.value.currentTime
}

const onAudioEnded = () => {
  isPlaying.value = false
}

const togglePlayPause = () => {
  if (isPlaying.value) {
    audioPlayer.value.pause()
  } else {
    audioPlayer.value.play()
  }
  isPlaying.value = !isPlaying.value
}

const changeVolume = () => {
  audioPlayer.value.volume = volume.value
}

const startAnalysis = async () => {
  isAnalyzing.value = true
  
  // 模拟分析过程
  await new Promise(resolve => setTimeout(resolve, 3000))
  
  // 生成模拟分析结果
  analysisResult.value = {
    aiProbability: Math.floor(Math.random() * 100),
    voiceType: '男性成年',
    language: '普通话',
    gender: '男性',
    emotion: '平静',
    naturalness: Math.floor(Math.random() * 40) + 60,
    fluency: Math.floor(Math.random() * 35) + 65,
    quality: Math.floor(Math.random() * 30) + 70,
    pitchVariation: '正常',
    formantDistribution: '规律',
    spectralFeatures: '标准',
    prosodyFeatures: '自然',
    anomalies: [
      {
        id: 1,
        title: '音调异常',
        description: '检测到不自然的音调变化',
        severity: 'medium',
        timestamp: 5.2,
        icon: '🔊'
      },
      {
        id: 2,
        title: '频谱异常',
        description: '频谱特征显示可能的合成痕迹',
        severity: 'high',
        timestamp: 12.8,
        icon: '📊'
      }
    ]
  }
  
  isAnalyzing.value = false
  activeTab.value = 'basic'
  
  // 绘制声纹图
  drawVoiceprint()
}

const quickCheck = async () => {
  isAnalyzing.value = true
  
  // 快速检测
  await new Promise(resolve => setTimeout(resolve, 1000))
  
  analysisResult.value = {
    aiProbability: Math.floor(Math.random() * 50) + 30,
    voiceType: '女性成年',
    language: '普通话',
    naturalness: 85,
    fluency: 90,
    quality: 88
  }
  
  isAnalyzing.value = false
}

const drawWaveform = () => {
  const canvas = waveformCanvas.value
  if (!canvas) return
  
  const ctx = canvas.getContext('2d')
  const width = canvas.width
  const height = canvas.height
  
  // 清除画布
  ctx.clearRect(0, 0, width, height)
  
  // 绘制模拟波形
  ctx.strokeStyle = '#1e3c72'
  ctx.lineWidth = 2
  ctx.beginPath()
  
  for (let i = 0; i < width; i++) {
    const amplitude = Math.sin(i * 0.05) * Math.random() * 40
    const y = height / 2 + amplitude
    
    if (i === 0) {
      ctx.moveTo(i, y)
    } else {
      ctx.lineTo(i, y)
    }
  }
  
  ctx.stroke()
}

const drawVoiceprint = () => {
  const canvas = voiceprintCanvas.value
  if (!canvas) return
  
  const ctx = canvas.getContext('2d')
  const width = canvas.width
  const height = canvas.height
  
  // 清除画布
  ctx.clearRect(0, 0, width, height)
  
  // 绘制模拟声纹
  for (let i = 0; i < width; i += 2) {
    for (let j = 0; j < height; j += 2) {
      const intensity = Math.random()
      const color = `rgba(30, 60, 114, ${intensity})`
      ctx.fillStyle = color
      ctx.fillRect(i, j, 2, 2)
    }
  }
}

const playSegment = (timestamp) => {
  audioPlayer.value.currentTime = timestamp
  audioPlayer.value.play()
  isPlaying.value = true
}

const getScoreClass = (score) => {
  if (score >= 70) return 'high'
  if (score >= 40) return 'medium'
  return 'low'
}

const formatTime = (seconds) => {
  const mins = Math.floor(seconds / 60)
  const secs = Math.floor(seconds % 60)
  return `${mins}:${secs.toString().padStart(2, '0')}`
}

const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

const replayAudio = (record) => {
  console.log('重新播放:', record)
}

const reanalyzeAudio = (record) => {
  console.log('重新分析:', record)
}

// 生命周期
onMounted(() => {
  // 初始化
})

onUnmounted(() => {
  // 清理资源
  if (currentAudio.value) {
    URL.revokeObjectURL(currentAudio.value.url)
  }
  if (isRecording.value) {
    stopRecording()
  }
})
</script>

<style scoped>
.audio-detection {
  padding: 20px;
  max-width: 1600px;
  margin: 0 auto;
  background: #f8f9fa;
  min-height: 100vh;
}

/* 响应式设计 */
@media (max-width: 1600px) {
  .audio-detection {
    width: 90%;
  }
}

@media (max-width: 1200px) {
  .audio-detection {
    width: 95%;
  }
}

@media (max-width: 768px) {
  .audio-detection {
    width: 100%;
    padding: 10px;
  }
}

.page-header {
  text-align: center;
  margin-bottom: 30px;
}

.page-header h1 {
  font-size: 2.5em;
  color: #1e3c72;
  margin-bottom: 10px;
}

.upload-section {
  background: white;
  padding: 30px;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0,0,0,0.1);
  margin-bottom: 30px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 30px;
}

.upload-area {
  border: 2px dashed #ddd;
  border-radius: 10px;
  padding: 30px;
  text-align: center;
  transition: all 0.3s ease;
}

.upload-area:hover {
  border-color: #1e3c72;
  background: #f8f9fa;
}

.upload-icon {
  font-size: 3em;
  margin-bottom: 15px;
}

.upload-btn {
  padding: 12px 30px;
  background: #1e3c72;
  color: white;
  border: none;
  border-radius: 25px;
  cursor: pointer;
  font-size: 16px;
}

.record-section {
  text-align: center;
}

.record-section h3 {
  color: #1e3c72;
  margin-bottom: 20px;
}

.record-controls {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
}

.record-btn {
  padding: 15px 30px;
  background: #28a745;
  color: white;
  border: none;
  border-radius: 25px;
  cursor: pointer;
  font-size: 16px;
  transition: all 0.3s ease;
}

.record-btn.recording {
  background: #dc3545;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.05); }
  100% { transform: scale(1); }
}

.recording-time {
  color: #dc3545;
  font-weight: bold;
}

.audio-section {
  background: white;
  padding: 30px;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0,0,0,0.1);
  margin-bottom: 30px;
}

.player-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.player-header h3 {
  color: #1e3c72;
  margin: 0;
}

.audio-info {
  display: flex;
  gap: 20px;
  color: #666;
  font-size: 14px;
}

.control-buttons {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 20px;
}

.play-btn {
  padding: 10px 20px;
  background: #1e3c72;
  color: white;
  border: none;
  border-radius: 25px;
  cursor: pointer;
  font-size: 16px;
}

.time-display {
  color: #666;
  font-size: 14px;
}

.volume-control input {
  width: 100px;
}

.waveform-container {
  margin-bottom: 20px;
}

.waveform-container canvas {
  width: 100%;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.analysis-controls {
  display: flex;
  gap: 15px;
  justify-content: center;
}

.analyze-btn {
  padding: 12px 30px;
  background: #28a745;
  color: white;
  border: none;
  border-radius: 25px;
  cursor: pointer;
  font-size: 16px;
}

.analyze-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
}

.quick-check-btn {
  padding: 12px 30px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 25px;
  cursor: pointer;
  font-size: 16px;
}

.result-section {
  background: white;
  padding: 30px;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0,0,0,0.1);
  margin-bottom: 30px;
}

.result-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.overall-score {
  text-align: center;
}

.score-circle {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2em;
  font-weight: bold;
  color: white;
  margin-bottom: 5px;
}

.score-circle.high {
  background: #dc3545;
}

.score-circle.medium {
  background: #ffc107;
}

.score-circle.low {
  background: #28a745;
}

.score-label {
  font-size: 0.9em;
  color: #666;
}

.result-tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.tab-btn {
  padding: 10px 20px;
  border: 2px solid #e0e0e0;
  background: white;
  border-radius: 25px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.tab-btn.active {
  background: #1e3c72;
  color: white;
  border-color: #1e3c72;
}

.analysis-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

.analysis-card {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 10px;
}

.analysis-card h3 {
  color: #1e3c72;
  margin-bottom: 15px;
}

.feature-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.feature-item {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #eee;
}

.label {
  color: #666;
  font-weight: 500;
}

.value {
  color: #333;
}

.metrics-list {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.metric-item {
  display: flex;
  align-items: center;
  gap: 15px;
}

.metric-label {
  width: 80px;
  color: #666;
  font-size: 14px;
}

.metric-bar {
  flex: 1;
  height: 8px;
  background: #eee;
  border-radius: 4px;
  overflow: hidden;
}

.metric-fill {
  height: 100%;
  background: #1e3c72;
  transition: width 0.3s ease;
}

.metric-value {
  width: 40px;
  text-align: right;
  color: #666;
  font-size: 14px;
}

.voiceprint-analysis {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 30px;
}

.voiceprint-display {
  text-align: center;
}

.voiceprint-display h3 {
  color: #1e3c72;
  margin-bottom: 15px;
}

.voiceprint-display canvas {
  border: 1px solid #ddd;
  border-radius: 5px;
}

.voiceprint-details h3 {
  color: #1e3c72;
  margin-bottom: 15px;
}

.details-grid {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.detail-item {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
}

.detail-label {
  color: #666;
  font-weight: 500;
}

.detail-value {
  color: #333;
}

.anomaly-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.anomaly-item {
  display: flex;
  align-items: flex-start;
  gap: 15px;
  padding: 20px;
  border-radius: 10px;
}

.anomaly-item.high {
  background: #ffebee;
  border-left: 4px solid #dc3545;
}

.anomaly-item.medium {
  background: #fff3e0;
  border-left: 4px solid #ffc107;
}

.anomaly-icon {
  font-size: 1.5em;
  margin-top: 5px;
}

.anomaly-content {
  flex: 1;
}

.anomaly-content h4 {
  margin: 0 0 10px 0;
  color: #333;
}

.anomaly-content p {
  margin: 0 0 10px 0;
  color: #666;
  line-height: 1.5;
}

.anomaly-location {
  display: flex;
  align-items: center;
  gap: 15px;
}

.play-segment-btn {
  padding: 4px 8px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  font-size: 12px;
}

.history-section {
  background: white;
  padding: 30px;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}

.history-section h2 {
  color: #1e3c72;
  margin-bottom: 20px;
}

.history-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

.history-card {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 10px;
  border-left: 4px solid #1e3c72;
}

.history-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}

.history-header h4 {
  margin: 0;
  color: #333;
}

.history-result {
  padding: 4px 12px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: bold;
  color: white;
}

.history-result.high {
  background: #dc3545;
}

.history-result.medium {
  background: #ffc107;
}

.history-result.low {
  background: #28a745;
}

.history-details {
  margin-bottom: 15px;
}

.history-details p {
  margin: 5px 0;
  color: #666;
  font-size: 14px;
}

.history-actions {
  display: flex;
  gap: 10px;
}

.replay-btn, .reanalyze-btn {
  padding: 6px 12px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

.reanalyze-btn {
  background: #28a745;
}

@media (max-width: 768px) {
  .upload-section {
    grid-template-columns: 1fr;
  }
  
  .analysis-grid {
    grid-template-columns: 1fr;
  }
  
  .voiceprint-analysis {
    grid-template-columns: 1fr;
  }
  
  .history-grid {
    grid-template-columns: 1fr;
  }
  
  .control-buttons {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
}
</style> 